package MySQLConnection;

import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import model.BusinessCase;
import model.Case;
import model.ComponentWithBC;
import model.Criterion;
import model.Method;
import model.MethodApplication;
import model.Value;

import common.Enums.ComponentType;
import common.Enums.DAOType;
import common.Enums.DateRange;
import common.Exceptions.DAOException;

import DAO.DAOFactory;
import DAO.MetAppDAO;
import DAO.SessionDAO;

public class MySQLMetAppDAO implements MetAppDAO 
{
	private final static String TABLE_NAME = MySqlDAOFactory.DBName + "." + "methodapplication"; 
	private static MySQLMetAppDAO instance;
	
	public static MySQLMetAppDAO getInstance()
	{
		if(instance == null)
			instance = new MySQLMetAppDAO();
		
		return instance;
	}
	
	@Override
	public void insert(UUID bcID, MethodApplication item) throws DAOException 
	{
		String query = "INSERT INTO " + TABLE_NAME + "(metApp_id, bc_id, cas_id,crt_id,met_id, val_id, parentMetID, createdDate) VALUES(?, ?, ?, ?, ?, ?, ?, ?);";

		try 
		{
			if(bcID != null)
			{
				PreparedStatement preStatement = MySqlDAOFactory.getInstance().prepareStatement(query);
				preStatement.setString(1, item.getID().toString());
				preStatement.setString(2, bcID.toString());
				
				if(item.getCaso() != null)
					preStatement.setString(3, item.getCaso().getID().toString());
				else
					preStatement.setNull(3, java.sql.Types.VARCHAR);
				
				if(item.getCriterion() != null)
					preStatement.setString(4, item.getCriterion().getID().toString());
				else
					preStatement.setNull(4, java.sql.Types.VARCHAR);
				
				if(item.getMethod() != null)
					preStatement.setString(5, item.getMethod().getID().toString());
				else
					preStatement.setNull(5, java.sql.Types.VARCHAR);
				
				if(item.getValue() != null)
					preStatement.setString(6, item.getValue().getID().toString());
				else
					preStatement.setNull(6, java.sql.Types.VARCHAR);
				
				if(item.getParentMetID() != null)
					preStatement.setString(7, item.getParentMetID().toString());
				else
					preStatement.setNull(7, java.sql.Types.VARCHAR);

				preStatement.setTimestamp(8, new java.sql.Timestamp(new java.util.Date().getTime()));
				preStatement.executeUpdate();
			}
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The insert method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			MySqlDAOFactory.getInstance().closeConnection();
		}
	}

	@Override
	public void update(MethodApplication item) throws DAOException 
	{
		String query = "SELECT * FROM " + TABLE_NAME + " WHERE metApp_id = '" + item.getID().toString() + "';";

		try 
		{
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			
			if(dataSet.next())
			{
				String itemID = dataSet.getString("metApp_id");
				BusinessCase bc = SessionDAO.getInstance().getCachedBC();
				
				if(itemID != null && bc != null)
				{
					String updateQuery = "UPDATE " + TABLE_NAME + " set bc_id = ?, crt_id = ?, met_id = ?, cas_id = ?, val_id = ?, createdDate = ? WHERE metApp_id = ?";
					
					PreparedStatement preStatement = MySqlDAOFactory.getInstance().prepareStatement(updateQuery);
					preStatement.setString(1, bc.getID().toString());
					
					if(item.getCriterion() != null)
						preStatement.setString(2, item.getCriterion().getID().toString());
					else
						preStatement.setNull(2, java.sql.Types.VARCHAR);
					
					if(item.getMethod() != null)
						preStatement.setString(3, item.getMethod().getID().toString());
					else
						preStatement.setNull(3, java.sql.Types.VARCHAR);
					
					if(item.getCaso() != null)
						preStatement.setString(4, item.getCaso().getID().toString());
					else
						preStatement.setNull(4, java.sql.Types.VARCHAR);
					
					if(item.getValue() != null)
						preStatement.setString(5, item.getValue().getID().toString());
					else
						preStatement.setNull(5, java.sql.Types.VARCHAR);
					
					preStatement.setTimestamp(6, new java.sql.Timestamp(new java.util.Date().getTime()));
					preStatement.setString(7, item.getID().toString());
					
					preStatement.executeUpdate();
						
					if(dataSet.next())
						System.err.println("WARING: Two or more " + TABLE_NAME + " with the same ID were found in the database. metApp_id = " + item.getID());
				}
			}
			else
				throw new DAOException("The " + TABLE_NAME + "  identified by the id " + item.getID() + " hasn't been found in the database.");
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The insert method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			MySqlDAOFactory.getInstance().closeConnection();
		}
	}

	@Override
	public void delete(UUID id) throws DAOException 
	{
		String query = "SELECT * FROM " + TABLE_NAME + " WHERE metApp_id = '" + id + "';";

		try 
		{
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			
			if(dataSet.next())
			{
				String deleteQuery = "DELETE FROM " + TABLE_NAME + " WHERE metApp_id = '" + id + "'";
				
				statement = MySqlDAOFactory.getInstance().createStatement();
				if(statement.executeUpdate(deleteQuery) == 0)
					throw new DAOException("The " + TABLE_NAME +" identified by the id " + id + " couldn't be deleted due to an unknown error.");
					
				if(dataSet.next())
					System.err.println("WARING: Two or more " + TABLE_NAME +" with the same ID were found in the database. metApp_id = " + id);
			}
			else
				throw new DAOException("The " + TABLE_NAME + " identified by the id " + id + " hasn't been found in the database.");
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The delete method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			MySqlDAOFactory.getInstance().closeConnection();
		}
	}

	@Override
	public MethodApplication getByID(UUID id) throws DAOException 
	{
		MethodApplication metApp = null;
		String query = "SELECT * FROM " + TABLE_NAME + " WHERE metApp_id = '" + id.toString() + "';";
		boolean lockOwner = false;

		try 
		{
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			
			if(dataSet.next())
			{
				String temp = dataSet.getString("met_id");
				UUID metID = (temp != null) ? UUID.fromString(temp) : null;
				
				temp = dataSet.getString("cas_id");
				UUID caseID = (temp != null) ? UUID.fromString(temp) : null;
				
				temp = dataSet.getString("crt_id");
				UUID crtID = (temp != null) ? UUID.fromString(temp) : null;
				
				temp = dataSet.getString("val_id");
				UUID valID = (temp != null) ? UUID.fromString(temp) : null;

				temp = dataSet.getString("parentMetID");
				UUID parentMetID = (temp != null) ? UUID.fromString(temp) : null;
				
				UUID metAppID = UUID.fromString(dataSet.getString("metApp_id"));
				UUID bcID = UUID.fromString(dataSet.getString("bc_id"));
				Date createdDate = new Date(dataSet.getTimestamp("createdDate").getTime());
				
				lockOwner = MySqlDAOFactory.lockConnection.tryLock();
				metApp = new MethodApplication(metAppID, crtID, caseID, metID, valID, parentMetID, bcID, createdDate);
				
				if(dataSet.next())
					System.err.println("WARING: Two or more " + TABLE_NAME + " with the same ID were found in the database. metApp_id = " + id);
			}
			else
				throw new DAOException("The " + TABLE_NAME + " identified by the id " + id + " hasn't been found in the database.");
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The getByID method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			if(lockOwner)
			{
				MySqlDAOFactory.lockConnection.unlock();
				MySqlDAOFactory.getInstance().closeConnection();
			}
		}
		
		return metApp;
	}

	@Override
	public List<MethodApplication> getAll() throws DAOException 
	{
		String query = "SELECT metApp_id FROM " + TABLE_NAME + ";";
		List<MethodApplication> metApps = new LinkedList<MethodApplication>();
		boolean lockOwner = false;
		
		try 
		{
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			
			lockOwner = MySqlDAOFactory.lockConnection.tryLock();
			
			while(dataSet.next())
			{
				MethodApplication metApp = getByID(UUID.fromString(dataSet.getString("metApp_id")));
				metApps.add(metApp);
			}
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The getAll method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			if(lockOwner)
			{
				MySqlDAOFactory.lockConnection.unlock();
				MySqlDAOFactory.getInstance().closeConnection();
			}
		}
		
		return metApps;
	}
	
	@Override
	public List<MethodApplication> getAllByBcID(UUID itemID) throws DAOException 
	{
		String query = "SELECT metApp_id FROM " + TABLE_NAME + " WHERE bc_id = '" + itemID + "';";
		List<MethodApplication> metApps = new LinkedList<MethodApplication>();
		boolean lockOwner = false;
		
		try 
		{
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			
			lockOwner = MySqlDAOFactory.lockConnection.tryLock();
			
			while(dataSet.next())
			{
				MethodApplication metApp = getByID(UUID.fromString(dataSet.getString("metApp_id")));
				metApps.add(metApp);
			}
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The getAll method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			if(lockOwner)
			{
				MySqlDAOFactory.lockConnection.unlock();
				MySqlDAOFactory.getInstance().closeConnection();
			}
		}
		
		return metApps;
	}

	@Override
	public List<Case> getCasesByBcID(UUID itemID) throws DAOException 
	{
		String query = "SELECT distinct cas_id FROM " + TABLE_NAME + " WHERE bc_id = '" + itemID + "';";
		List<Case> cases = new LinkedList<Case>();

		for(Object cmp : getComponents(query, ComponentType.CASE))
		{
			Case cas = (Case)cmp;
			cases.add(cas);
		}
	
		return cases;
	}

	@Override
	public List<Criterion> getCriteriaByBcID(UUID itemID) throws DAOException 
	{
		String query = "SELECT distinct crt_id FROM " + TABLE_NAME + " WHERE bc_id = '" + itemID + "';";
		List<Criterion> criteria = new LinkedList<Criterion>();
		
		for(Object cmp : getComponents(query, ComponentType.CRITERION))
		{
			Criterion crt = (Criterion)cmp;
			criteria.add(crt);
		}
		
		return criteria;
	}
	
	@Override
	public List<Method> getMethodsByBcID(UUID itemID) throws DAOException
	{
		String query = "SELECT distinct met_id FROM " + TABLE_NAME + " WHERE bc_id = '" + itemID + "';";
		List<Method> methods = new LinkedList<Method>();
		
		for(Object cmp : getComponents(query, ComponentType.METHOD))
		{
			Method met = (Method)cmp;
			methods.add(met);
		}
		
		return methods;
	}
	
	@Override
	public List<Value> getValuesByBcID(UUID itemID) throws DAOException
	{
		String query = "SELECT distinct val_id FROM " + TABLE_NAME + " WHERE bc_id = '" + itemID + "';";
		List<Value> values = new LinkedList<Value>();
		
		for(Object cmp : getComponents(query, ComponentType.VALUE))
		{
			Value val = (Value)cmp;
			values.add(val);
		}
		
		return values;
	}
	
	@Override
	public List<Value> getValuesByMethodID(UUID itemID) throws DAOException
	{
		String query = "SELECT distinct val_id FROM " + TABLE_NAME + " WHERE met_id = '" + itemID + "';";
		List<Value> values = new LinkedList<Value>();
		
		for(Object cmp : getComponents(query, ComponentType.VALUE))
		{
			Value val = (Value)cmp;
			values.add(val);
		}
		
		return values;
	}
	
	@Override
	public Value getValue(UUID casID, UUID metID) throws DAOException
	{
		Value retVal = null;
		String query = "SELECT distinct val_id FROM " + TABLE_NAME + " WHERE met_id = '" + metID + "' and cas_id = '" + casID + "';";
		
		if(getComponents(query, ComponentType.VALUE).size() > 0)
			retVal = (Value)getComponents(query, ComponentType.VALUE).get(0); 
		
		return retVal;
	}
	
	@Override
	public List<MethodApplication> getAllByCaseAndCriterionID(UUID bcID, UUID criterionID, UUID caseID) throws DAOException 
	{
		String condition = " WHERE bc_id = '" + bcID +  "' and crt_id = '" + criterionID + "' and cas_id = '" + caseID + "'";
		
		return getAllByComponentFilter(condition);
	}
	
	@Override
	public List<MethodApplication> getAllByCriterionID(UUID criterionID) throws DAOException 
	{
		String condition = " WHERE crt_id = '" + criterionID + "'";
		
		return getAllByComponentFilter(condition);
	}
	
	private List<MethodApplication> getAllByComponentFilter(String condition) throws DAOException 
	{
		String query = "SELECT metApp_id FROM " + TABLE_NAME + condition;
		List<MethodApplication> metApps = new LinkedList<MethodApplication>();
		boolean lockOwner = false;
		
		try 
		{
			lockOwner = MySqlDAOFactory.lockConnection.tryLock();
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			
			ResultSet dataSet = statement.executeQuery(query);
			while(dataSet.next())
			{
				MethodApplication metApp = getByID(UUID.fromString(dataSet.getString("metApp_id")));
				metApps.add(metApp);
			}
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The getAll method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			if(lockOwner)
			{
				MySqlDAOFactory.lockConnection.unlock();
				MySqlDAOFactory.getInstance().closeConnection();
			}
		}
		
		return metApps;
	}

	@Override
	public MethodApplication getOriginMetApp(ComponentType cmpType, UUID cmpID) throws DAOException
	{
		MethodApplication origin = null;
		String query = "SELECT metApp_id FROM " + TABLE_NAME + " WHERE cmpID = ? order by createdDate asc";
		
		try 
		{
			String cmp = null;
			switch(cmpType)
			{
				case CASE:
					cmp = "cas_id";
					break;
					
				case CRITERION:
					cmp = "crt_id";
					break;
					
				case METHOD:
					cmp = "met_id";
					break;
					
				case VALUE:
					cmp = "val_id";
					break;
			}
			
			query = query.replace("cmpID", cmp);
			PreparedStatement preStatement = MySqlDAOFactory.getInstance().prepareStatement(query);
			preStatement.setString(1, cmpID.toString());
			
			ResultSet dataSet = preStatement.executeQuery();
			
			if(dataSet.next())
				origin = getByID(UUID.fromString(dataSet.getString("metApp_id")));
		}
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The delete method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			MySqlDAOFactory.getInstance().closeConnection();
		}
		
		return origin;
	}
	
	private List<Object> getComponents(String query, ComponentType cmpType) throws DAOException 
	{
		List<Object> components = new LinkedList<Object>();
		boolean lockOwner = false;
		
		try 
		{
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			
			lockOwner = MySqlDAOFactory.lockConnection.tryLock();
			
			while(dataSet.next())
			{
				Object cmp = null;
				switch(cmpType)
				{
					case CASE:
						String casID = dataSet.getString("cas_id");
						if(casID != null)
						{
							UUID caseID = UUID.fromString(casID);
							cmp = DAOFactory.getDAOFactory(DAOType.MYSQL).getCaseDAO().getByID(caseID);
						}
						break;
						
					case CRITERION:
						String crt_id = dataSet.getString("crt_id");
						if(crt_id != null)
						{
							UUID crtID = UUID.fromString(crt_id);
							cmp = DAOFactory.getDAOFactory(DAOType.MYSQL).getCriterionDAO().getByID(crtID);
						}
						break;
						
					case METHOD:
						String met_id = dataSet.getString("met_id");
						if(met_id != null)
						{
							UUID metID = UUID.fromString(met_id);
							cmp = DAOFactory.getDAOFactory(DAOType.MYSQL).getMethodDAO().getByID(metID);
						}
						break;
						
					case VALUE:
						String val_id = dataSet.getString("val_id");
						if(val_id != null)
						{
							UUID valID = UUID.fromString(val_id);
							cmp = DAOFactory.getDAOFactory(DAOType.MYSQL).getValueDAO().getByID(valID);
						}
						break;
				}
				
				if(cmp != null)
					components.add(cmp);
			}
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The getComponents method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			if(lockOwner)
			{
				MySqlDAOFactory.lockConnection.unlock();
				MySqlDAOFactory.getInstance().closeConnection();
			}
		}
		
		return components;
	}
	
	@Override
	public List<ComponentWithBC<Criterion>> getCriterionByFilters(UUID bcID, UUID parentMetID, DateRange dateRange, String search) throws DAOException
	{
		boolean lockOwner = false;
		List<ComponentWithBC<Criterion>> criteria = new LinkedList<ComponentWithBC<Criterion>>();
		java.util.Date lastUpdatedFilter = null;
		String query = "SELECT DISTINCT crt_id, bc_id FROM " + TABLE_NAME + " CONDITION order by createdDate asc";
		
		String where = "WHERE parentMetID != '" + parentMetID + "' ";
		if(bcID != null)
			where += "AND bc_id = '" + bcID + "'";
		
		query = query.replace("CONDITION", where);
		
		try 
		{
			lockOwner = MySqlDAOFactory.lockConnection.tryLock();
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			lastUpdatedFilter = MySqlDAOFactory.getLastUpdatedFilter(dateRange);
			
			while(dataSet.next())
			{
				if(dataSet.getString("crt_id") != null)
				{
					boolean canAdd = true;
					Criterion crt = MySqlDAOFactory.getInstance().getCriterionDAO().getByID(UUID.fromString(dataSet.getString("crt_id")));
					BusinessCase bc = MySqlDAOFactory.getInstance().getBcDAO().getByID(UUID.fromString(dataSet.getString("bc_id")));
					
					if(lastUpdatedFilter != null)
						canAdd = crt.getLastUpdated().after(lastUpdatedFilter);
					if(canAdd && search != null && search.trim() != "")
						canAdd = (crt.getName().toLowerCase().contains(search.toLowerCase()));
					
					if(canAdd)
						criteria.add(new ComponentWithBC<Criterion>(bc, crt));
				}
			}
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The delete method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			if(lockOwner)
			{
				MySqlDAOFactory.lockConnection.unlock();
				MySqlDAOFactory.getInstance().closeConnection();
			}
		}
		
		return criteria;
	}
	
	@Override
	public List<ComponentWithBC<Method>> getMethodByFilters(UUID bcID, DateRange dateRange, String search) throws DAOException
	{
		boolean lockOwner = false;
		List<ComponentWithBC<Method>> methods = new LinkedList<ComponentWithBC<Method>>();
		java.util.Date lastUpdatedFilter = null;
		String query = "SELECT DISTINCT met_id, bc_id FROM " + TABLE_NAME + " CONDITION order by createdDate asc";
		
		String where = "";
		if(bcID != null)
			where = "WHERE bc_id = '" + bcID + "'";
		
		query = query.replace("CONDITION", where);
		
		try 
		{
			lockOwner = MySqlDAOFactory.lockConnection.tryLock();
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			lastUpdatedFilter = MySqlDAOFactory.getLastUpdatedFilter(dateRange);
			
			while(dataSet.next())
			{
				if(dataSet.getString("met_id") != null)
				{
					boolean canAdd = true;
					Method met = MySqlDAOFactory.getInstance().getMethodDAO().getByID(UUID.fromString(dataSet.getString("met_id")));
					BusinessCase bc = MySqlDAOFactory.getInstance().getBcDAO().getByID(UUID.fromString(dataSet.getString("bc_id")));
					
					if(lastUpdatedFilter != null)
						canAdd = met.getLastUpdated().after(lastUpdatedFilter);
					if(canAdd && search != null && search.trim() != "")
						canAdd = (met.getName().toLowerCase().contains(search.toLowerCase()));
					
					if(canAdd)
						methods.add(new ComponentWithBC<Method>(bc, met));
				}
			}
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The delete method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			if(lockOwner)
			{
				MySqlDAOFactory.lockConnection.unlock();
				MySqlDAOFactory.getInstance().closeConnection();
			}
		}
		
		return methods;
	}
	
	@Override
	public List<ComponentWithBC<Case>> getCaseByFilters(UUID bcID, UUID parentBc, DateRange dateRange, String search) throws DAOException
	{
		boolean lockOwner = false;
		List<ComponentWithBC<Case>> cases = new LinkedList<ComponentWithBC<Case>>();
		java.util.Date lastUpdatedFilter = null;
		String query = "SELECT DISTINCT cas_id, bc_id FROM " + TABLE_NAME + " CONDITION order by createdDate asc";
		
		String where = "WHERE bc_id != '" + parentBc + "' ";
		if(bcID != null)
			where += "AND bc_id = '" + bcID + "'";
		
		query = query.replace("CONDITION", where);
		
		try 
		{
			lockOwner = MySqlDAOFactory.lockConnection.tryLock();
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			lastUpdatedFilter = MySqlDAOFactory.getLastUpdatedFilter(dateRange);
			
			while(dataSet.next())
			{
				if(dataSet.getString("cas_id") != null)
				{
					boolean canAdd = true;
					Case caso = MySqlDAOFactory.getInstance().getCaseDAO().getByID(UUID.fromString(dataSet.getString("cas_id")));
					BusinessCase bc = MySqlDAOFactory.getInstance().getBcDAO().getByID(UUID.fromString(dataSet.getString("bc_id")));
					
					if(lastUpdatedFilter != null)
						canAdd = caso.getLastUpdated().after(lastUpdatedFilter);
					if(canAdd && search != null && search.trim() != "")
						canAdd = (caso.getName().toLowerCase().contains(search.toLowerCase()));
					
					if(canAdd)
						cases.add(new ComponentWithBC<Case>(bc, caso));
				}
			}
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The delete method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			if(lockOwner)
			{
				MySqlDAOFactory.lockConnection.unlock();
				MySqlDAOFactory.getInstance().closeConnection();
			}
		}
		
		return cases;
	}
	
	@Override
	public List<MethodApplication> getValuesByFilters(UUID bcID, DateRange dateRange, String search) throws DAOException
	{
		boolean lockOwner = false;
		List<MethodApplication> metApps = new LinkedList<MethodApplication>();
		java.util.Date lastUpdatedFilter = null;
		String query = "SELECT metapp_id, val_id FROM " + TABLE_NAME + " CONDITION order by createdDate asc";
		
		String where = "";
		if(bcID != null)
			where = "WHERE bc_id = '" + bcID + "'";
		
		query = query.replace("CONDITION", where);
		
		try 
		{
			lockOwner = MySqlDAOFactory.lockConnection.tryLock();
			Statement statement = MySqlDAOFactory.getInstance().createStatement();
			ResultSet dataSet = statement.executeQuery(query);
			lastUpdatedFilter = MySqlDAOFactory.getLastUpdatedFilter(dateRange);
			
			while(dataSet.next())
			{
				if(dataSet.getString("val_id") != null)
				{
					boolean canAdd = true;
					MethodApplication metApp = getByID(UUID.fromString(dataSet.getString("metApp_id")));
					
					if(lastUpdatedFilter != null)
						canAdd = metApp.getValue().getLastUpdated().after(lastUpdatedFilter);
					if(canAdd && search != null && search.trim() != "")
						canAdd = (metApp.getCriterion().getName().toLowerCase().contains(search.toLowerCase()));
					
					if(canAdd)
						metApps.add(metApp);
				}
			}
		}
		catch (DAOException e) 
		{
			throw e;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The delete method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			if(lockOwner)
			{
				MySqlDAOFactory.lockConnection.unlock();
				MySqlDAOFactory.getInstance().closeConnection();
			}
		}
		
		return metApps;
	}

	@Override
	public boolean assertIsOnlyReference(ComponentType cmpType, UUID cmpID) throws DAOException 
	{
		boolean isOnlyReference = true;
		String query = "SELECT metApp_id FROM " + TABLE_NAME + " WHERE cmpID = ?";
		
		try 
		{
			String cmp = null;
			switch(cmpType)
			{
				case CRITERION:
					cmp = "crt_id";
					break;
					
				case METHOD:
					cmp = "met_id";
					break;
					
				case VALUE:
					cmp = "val_id";
					break;
			}
			
			query = query.replace("cmpID", cmp);
			PreparedStatement preStatement = MySqlDAOFactory.getInstance().prepareStatement(query);
			preStatement.setString(1, cmpID.toString());
			
			ResultSet dataSet = preStatement.executeQuery();
			
			if(dataSet.next())
				isOnlyReference = false;
		}
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The delete method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			MySqlDAOFactory.getInstance().closeConnection();
		}
		
		return isOnlyReference;
	}

	@Override
	public boolean assertIsOnlyCrt(UUID crtID, UUID parentMetID) throws DAOException 
	{
		boolean isOnlyReference = true;
		String query = "SELECT metApp_id FROM " + TABLE_NAME + " WHERE crt_id = ? and parentMetID != ?";
		
		try 
		{
			PreparedStatement preStatement = MySqlDAOFactory.getInstance().prepareStatement(query);
			preStatement.setString(1, crtID.toString());
			preStatement.setString(2, parentMetID.toString());
			
			ResultSet dataSet = preStatement.executeQuery();
			
			if(dataSet.next())
				isOnlyReference = false;
		}
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The delete method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			MySqlDAOFactory.getInstance().closeConnection();
		}
		
		return isOnlyReference;
	}

	@Override
	public void insert(MethodApplication item) throws DAOException { throw new DAOException("METHOD NOT IMPLEMENTED!! Please use 'insert(UUID bcID, MethodApplication item)' instead"); }


	@Override
	public boolean isComponentReused(ComponentType cmpType, UUID cmpID, UUID bcID) throws DAOException 
	{
		boolean isReused = false;
		String query = "SELECT metApp_id FROM " + TABLE_NAME + " WHERE cmpID = ? and bc_id != ?";
		
		try 
		{
			String cmp = null;
			switch(cmpType)
			{
				case CRITERION:
					cmp = "crt_id";
					break;
					
				case METHOD:
					cmp = "met_id";
					break;
					
				case VALUE:
					cmp = "val_id";
					break;
					
				case CASE:
					cmp = "cas_id";
					break;
			}
			
			query = query.replace("cmpID", cmp);
			PreparedStatement preStatement = MySqlDAOFactory.getInstance().prepareStatement(query);
			preStatement.setString(1, cmpID.toString());
			preStatement.setString(2, bcID.toString());
			
			ResultSet dataSet = preStatement.executeQuery();
			
			if(dataSet.next())
				isReused = true;
		}
		catch (SQLException e) 
		{
			e.printStackTrace();
			throw new DAOException("The 'isComponentReused' method failed due to some Query error: " + e.getMessage(), e);
		}
		finally
		{
			MySqlDAOFactory.getInstance().closeConnection();
		}
		
		return isReused;
	}
}
